package com.yizisu.basemvvm

import android.app.Activity
import android.app.ActivityManager
import android.app.Application
import android.content.Context
import android.content.Intent
import android.graphics.Point
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log
import com.billy.android.swipe.SmartSwipeBack
import com.google.gson.Gson
import com.orhanobut.logger.AndroidLogAdapter
import com.orhanobut.logger.Logger
import com.orhanobut.logger.PrettyFormatStrategy
import com.yizisu.basemvvm.mvvm.MvvmActivity
import com.yizisu.basemvvm.utils.CrashHelper
import com.yizisu.basemvvm.utils.MvvmConf
import com.yizisu.basemvvm.utils.SP_FILE_NAME
import com.yizisu.basemvvm.utils.ScreenAdaptation
import okhttp3.*
import java.lang.StringBuilder
import java.nio.charset.Charset
import java.util.concurrent.TimeUnit


/**
 * 若红楼梦空，亦初心不变
 * 作者：kotle
 * 包名：com.yizisu.yzsbaselib
 * 时间：2018/10/1 10:06
 * 描述：okhttp工具类，方便快速的访问网络信息
 */
//gson
val gson by lazy { Gson() }

//主线程的handle
val mainHandler by lazy { Handler(Looper.getMainLooper()) }

//给外部调用创建okHttp设置参数的回调
private var clientCall: ((OkHttpClient.Builder) -> Unit)? = null

//okHttp构建器
val okHttpClientBuilder: OkHttpClient.Builder by lazy { OkHttpClient().newBuilder() }

//okHttp对象
val okHttpClient: OkHttpClient by lazy {
    okHttpClientBuilder.connectTimeout(3, TimeUnit.MINUTES)
    okHttpClientBuilder.readTimeout(3, TimeUnit.MINUTES)
    okHttpClientBuilder.writeTimeout(3, TimeUnit.MINUTES)
    clientCall?.invoke(okHttpClientBuilder)
    okHttpClientBuilder.addInterceptor {
        httpRequestLog(it)
    }
    okHttpClientBuilder.build()
}

//全局的application对象
lateinit var app: Application

//启动的activity集合
val activityList = mutableListOf<Activity>()

/**
 * {@see com.yizisu.basemvvm.utils.MvvmConfig}应该在此方法之前设置
 */
fun initMvvmLib(application: Application, client: ((OkHttpClient.Builder) -> Unit)? = null) {
    app = application
    clientCall = client
    initSp()
    initSwipeBack()
    initLog()
    Thread.setDefaultUncaughtExceptionHandler(CrashHelper)
    application.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {
        override fun onActivityPaused(activity: Activity) {
        }

        override fun onActivityStarted(activity: Activity) {
        }

        override fun onActivityDestroyed(activity: Activity) {
            activityList.remove(activity)
        }

        override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
            setScreenAdaptation(activity)
        }

        override fun onActivityStopped(activity: Activity) {
        }

        override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
            setScreenAdaptation(activity)
            activityList.add(activity)
        }

        override fun onActivityResumed(activity: Activity) {
        }
    })
}

//是否开启屏幕适配,支持所有activity，字体过大可以调整缩放因子
fun setScreenAdaptation(activity: Activity) {
    //是否开启屏幕适配
    if (MvvmConf.IS_CAN_SCREEN_ADAPTATION) {
        if (activity is MvvmActivity) {
            if (activity.isNeedScreenAdaptation()) {
                ScreenAdaptation.setCustomDensity(activity)
            }
        } else {
            ScreenAdaptation.setCustomDensity(activity)
        }
    }
}

/**
 * 设置SP存储的文件名
 */
private fun initSp() {
    SP_FILE_NAME = app.packageName.replace(".", "_")
}

/**
 * 侧滑返回
 */
private fun initSwipeBack() {
    //主Activity不需要侧滑返回功能，其它Activity都采用仿微信侧滑返回效果
    SmartSwipeBack.activitySlidingBack(app) { activity ->
        //根据传入的activity，返回true代表需要侧滑返回；false表示不需要侧滑返回
        var isNeedBack = true
        if (activity is MvvmActivity) {
            isNeedBack = activity.isCanSwipeBack()
        }
        isNeedBack
    }
}

/**
 * 初始化日志
 */
private fun initLog() {
    //不是debug模式不初始化
    if (!MvvmConf.IS_DEBUG) {
        return
    }
    //日志打印
    val formatStrategy = PrettyFormatStrategy.newBuilder()
        .showThreadInfo(false)  // (Optional) Whether to show thread info or not. Default true
        .methodCount(0)         // (Optional) How many method line to show. Default 2
        .methodOffset(7)        // (Optional) Hides internal method calls up to offset. Default 5
//            .logStrategy(customLog) // (Optional) Changes the log strategy to print out. Default LogCat
        .tag("--->")   // (Optional) Global tag for every log. Default PRETTY_LOGGER
        .build()
    Logger.addLogAdapter(AndroidLogAdapter(formatStrategy))
}

/**
 * 打印Http请求日志
 */
private fun httpRequestLog(chain: Interceptor.Chain): Response {
    val request = chain.request()
    if (!MvvmConf.IS_DEBUG) {
        //不是debug模式直接返回
        return chain.proceed(request)
    }
    val bodyStr = StringBuilder()
    val requestParams = when (val body = request.body()) {
        is FormBody -> {
            repeat(body.size()) {
                bodyStr.append(body.encodedName(it))
                bodyStr.append(":")
                bodyStr.append(body.encodedValue(it))
                bodyStr.append(",")
            }
            bodyStr.toString()
        }
        else -> {
            bodyStr.append("不是FormBody，不支持打印请求参数").toString()
        }
    }
    Logger.i("发送请求：${request.url()}\n请求参数：${requestParams}\n请求头:${request.headers()}")
    val t1 = System.nanoTime()
    val response = chain.proceed(request)
    val t2 = System.nanoTime()
    val source = response.body()?.source()
    source?.request(java.lang.Long.MAX_VALUE) // Buffer the entire body.
    val buffer = source?.buffer()?.clone()
    val responseStr = buffer?.readString(Charset.forName("UTF-8"))
    if ((responseStr?.startsWith('{') == true ||
                responseStr?.startsWith('[') == true) && (responseStr.endsWith('}') || responseStr.endsWith(
            ']'
        ))
    ) {
        Logger.json(
            "{\'响应链接\':\'${response.request().url()}\',\'响应时间\':\'${(t2 - t1) / 1e6} ms\'," +
                    "\'响应数据\':${responseStr}}"
        )
    } else {
        Logger.v(
            "{\'响应链接\':\'${response.request().url()}\',\n\'响应时间\':\'${(t2 - t1) / 1e6} ms\',\n" +
                    "\'响应数据\':${responseStr}}"
        )
    }
    return response
}

fun Any.printBundle(intent: Intent?) {
    val bundle = intent?.extras ?: return
    logI("开始打印Intent")
    bundle.keySet().forEach {
        logI("key:${it} value:${bundle.get(it)}")
    }
    logI("结束打印Intent")
}

fun Any.logI(msg: String?) {
    if (MvvmConf.IS_DEBUG) {
        Logger.i(this::class.java.simpleName + "--->" + msg)
    }
}

fun Any.logE(msg: String?) {
    if (MvvmConf.IS_DEBUG) {
        Logger.e(this::class.java.simpleName + "--->" + msg)
    }
}

fun Any.logV(msg: String?) {
    if (MvvmConf.IS_DEBUG) {
        Logger.v(this::class.java.simpleName + "--->" + msg)
    }
}

fun Any.logD(msg: String?) {
    if (MvvmConf.IS_DEBUG) {
        Logger.d(this::class.java.simpleName + "--->" + msg)
    }
}

fun Any.logW(msg: String?) {
    if (MvvmConf.IS_DEBUG) {
        Logger.w(this::class.java.simpleName + "--->" + msg)
    }
}